#include <windows.h>


#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#include <stdlib.h>
#include <cmath>
#include <iostream>
#include "complex.h"

#define rad 0.3
#define pi 3.1415926535897

using namespace std;

#define W          400
#define PIXEL_SIZE      0.03

int tec_point = -1;

struct Vertex {
    struct complex pos;
};

class Graf {
public:
    int n;
    struct Vertex *vertexes;
    int *matrix;
    Graf(int a = 0): n(a)
    {
        int i;
        vertexes = new struct Vertex[a];
        matrix = new int[a * a];
        for (i = 1; i <= a; i++)
        {
            (vertexes + i - 1)->pos.x = rad * cos(2 * pi * (i - 1) / a);
            (vertexes + i - 1)->pos.y = rad * sin(2 * pi * (i - 1) / a);
        }
        for (i = 1; i<=a*a; i++)
        {
            if ((i - 1) % a != (i - 1) / a)
                *(matrix + i - 1) = 1;
        }
        cout << "Born!" << endl;
    }
    ~Graf()
    {
        delete[] matrix;
        delete[] vertexes;
        cout << "Dead!" << endl;
    }
    void add(int i, int j);
    void del(int i, int j);
    bool edge(int i, int j);

};
void Graf :: add(int i, int j)
{
    *(matrix + (i - 1) * n + j - 1) = 1;
    *(matrix + (j - 1) * n + i - 1) = 1;
}

void Graf :: del(int i, int j)
{
    *(matrix + (i - 1) * n + j - 1) = 0;
    *(matrix + (j - 1) * n + i - 1) = 0;
}

ostream& operator<<(ostream& out, const Graf& c)
{
    int i, j;
    for (i = 1; i <= c.n; i++)
    {
        for (j = 1; j <= c.n; j++)
            out << *(c.matrix + (i - 1) * c.n + j - 1) << " ";
        out << endl;
    }
    return out;
}

Graf g(5);

void draw(void)
{
    int i, j;
    glClear(GL_COLOR_BUFFER_BIT);

    for (j = 1; j <= g.n * g.n; j++)
    {
        if (*(g.matrix + j - 1) == 1)
        {
            glColor3f(1, 1, 0);
            glBegin(GL_LINES);
                glVertex2f(g.vertexes[(j - 1) % g.n].pos.x + PIXEL_SIZE / 2, g.vertexes[(j - 1) % g.n].pos.y + PIXEL_SIZE / 2);
                glVertex2f(g.vertexes[(j - 1) / g.n].pos.x + PIXEL_SIZE / 2, g.vertexes[(j - 1) / g.n].pos.y + PIXEL_SIZE / 2);
            glEnd();
        }
    }

    for (i = 1; i <= g.n; i++)
    {
        glColor3f(0, 0.3, 1);
        glBegin(GL_POLYGON);
            glVertex2f(g.vertexes[i - 1].pos.x, g.vertexes[i - 1].pos.y);
            glVertex2f(g.vertexes[i - 1].pos.x + PIXEL_SIZE, g.vertexes[i - 1].pos.y);
            glVertex2f(g.vertexes[i - 1].pos.x + PIXEL_SIZE, g.vertexes[i - 1].pos.y + PIXEL_SIZE);
            glVertex2f(g.vertexes[i - 1].pos.x, g.vertexes[i - 1].pos.y + PIXEL_SIZE);
        glEnd();
        //cout << g.vertexes[i - 1].pos.x << " " << g.vertexes[i - 1].pos.y << endl;
    }
    glColor3f(1, 1, 0);
    glBegin(GL_POLYGON);
        glVertex2f(1, 1);
        glVertex2f(1-PIXEL_SIZE, 1);
        glVertex2f(1-PIXEL_SIZE, 1-PIXEL_SIZE);
        glVertex2f(1, 1-PIXEL_SIZE);
    glEnd();

    glColor3f(1, 1, 0);
    glBegin(GL_POLYGON);
        glVertex2f(-1, -1);
        glVertex2f(PIXEL_SIZE -1, -1);
        glVertex2f(PIXEL_SIZE -1, PIXEL_SIZE-1);
        glVertex2f(-1, PIXEL_SIZE-1);
    glEnd();
    glFlush();
    glutSwapBuffers();
}

//void glutMouseFunc(void (*mouse_click)(int button, int state, int x, int y));
//void glutMotionFunc(void (*mouse_drag) (int x,int y));


void mouse_click(int button, int state, int x, int y)
{
    int i;
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            cout << "DOWN" << endl;
            for(i = 1; i <= g.n; i++)
            {
                if ((g.vertexes[i - 1].pos.x <= 1.0*(x-W/2)/(W/2)) && (g.vertexes[i - 1].pos.x + PIXEL_SIZE >= 1.0*(x-W/2)/(W/2)) && (g.vertexes[i - 1].pos.y<= 1.0*(W/2-y)/(W/2)) && (g.vertexes[i - 1].pos.y + PIXEL_SIZE >= 1.0*(W/2-y)/(W/2)))
                {
                    tec_point = i-1;
                    cout << "Get it !!! " << i-1 << endl;
                    break;
                }
            }
        }
        else
        {
            cout << "UP " << tec_point << endl;
            tec_point = -1;

        }
    }
}

void mouse_drag(int x, int y)
{
    if (tec_point != -1)
    {
        g.vertexes[tec_point].pos.x = 1.0*(x-W/2)/(W/2);
        g.vertexes[tec_point].pos.y = 1.0*(W/2-y)/(W/2);
    }
    cout << "DRAG " << tec_point << " " << 1.0*(x - W/2)/(W/2) << " " << 1.0*(W/2-y)/(W/2) << endl;
}

void timf(int value) // Timer function
{
    glutPostRedisplay(); // Redraw windows
    glutTimerFunc(40, timf, 0); // Setup next timer
}


int main(int argc, char *argv[])
{
    g.add(1,2);
    g.add(2,3);
    g.del(2,3);
    cout << g;
    glutInit(&argc, argv);
    glutInitWindowSize(W, W);
    glutInitDisplayMode(GLUT_RGB);
    glutCreateWindow("Vertex");
    glutMouseFunc(mouse_click);
    glutMotionFunc(mouse_drag);


    glutDisplayFunc(draw);
    glClearColor(0, 0.4, 0.4, 0);
    glutTimerFunc(40, timf, 0); // Set up timer for 40ms, about 25 fps

    glutMainLoop();
    return 0;
}
